跳到主要内容

摄像头(以 OV5647 为例)

本节以 OV5647 摄像头模组为例,说明在 NG4520 平台的开发适配流程,涵盖硬件前置、设备树、驱动编译、系统加载和调试等完整步骤。

Camera 架构与名词解释

名词解释
ISP图像信号处理器,用于图像去噪、白平衡、色彩校正等。
Bayer即摄像头传感器,使用Bayer滤色阵列捕获图像。
CSI摄像头串行接口,用于摄像头与处理器之间的数据传输。
V4L2Linux内核的视频捕获和输出框架。
libargusNVIDIA提供的高级摄像头控制库。
Camera Core Library提供应用程序与内核模式V4L2驱动程序之间的控制和处理功能。
GStreamer开源的多媒体处理框架,用于音视频处理。
Host1xNVIDIA Tegra SoC中的主机接口控制器。
Aperture光圈控制,用于调节镜头的光圈大小。
UVCUSB视频类,用于USB摄像头的驱动程序。
VI视频输入模块,用于接收和处理视频数据。

Camera 软件架构说明

NVIDIA 平台支持两种 Camera 驱动架构:

  • Camera Core Library Interface:支持 ISP 访问和高级图像处理,应用层通过 libargus API 访问(如 nvgstcapture-1.0 工具)。
  • Direct V4L2 Interface:直接使用 V4L2 驱动,不支持 NVIDIA ISP。

建议开发时采用 Camera Core Library Interface,以便充分利用 NVIDIA ISP 能力。

OV5647 驱动适配流程

前置条件

  • 获取摄像头 I2C 地址及线序,确认 PWDN/RESET 引脚

  • 获取上电时序、外部时钟、支持分辨率/帧率、滤色器阵列类型(BGGR/GBRG/GRBG/RGGB)

  • 确认连接接口及 tegra_sinterface 对应关系(如 NG452X 平台 cam0=serial_c)

本例基于 Jetson Orin NX,硬件连接接口为 cam0。**

设备树配置

  • 创建设备树 Overlay 文件,路径示例如下:

    Linux_for_Tegra/source/hardware/nvidia/t23x/nv-public/overlay/tegra234-p3767-camera-p3768-ov5647.dts`
  • tegra-camera-platform 节点配置,配置视频流端口及连接关系,示例:

    tegra-capture-vi  {
    num-channels = <1>;
    ports {
    #address-cells = <1>;
    #size-cells = <0>;
    vi_port1: port@1 {
    reg = <0>;
    rbpcv2_ov5647_vi_in1: endpoint {
    port-index = <2>;
    bus-width = <2>;
    remote-endpoint = <&rbpcv2_ov5647_csi_out1>;
    };
    };
    };
    };
  • I2C 设备节点配置

    配置摄像头参数(I2C 地址、模式、时钟、分辨率等):

    rbpcv2_ov5647_c@36 {
    reset-gpios = <&gpio CAM0_RST GPIO_ACTIVE_HIGH>;
    pwdn-gpios = <&gpio CAM1_PWDN GPIO_ACTIVE_HIGH>;
    compatible = "ovti,ov5647";
    /* I2C device address */
    reg = <0x36>;
    /* V4L2 device node loation */
    devnode = "video0";
    /* Physical dimensions of sensor */
    physical_w = "3.670";
    physical_h = "2.740";
    sensor_model = "ov5647";
    use_sensor_mode_id = "true";

    clocks = <&bpmp TEGRA234_CLK_EXTPERIPH2>,
    <&bpmp TEGRA234_CLK_PLLP_OUT0>;
    clock-names = "extperiph2", "pllp_grtba";
    mclk = "extperiph2";
    clock-frequency = <24000000>;

    mode0 { /* ov5647_MODE0_1920x1080_30FPS */
    mclk_khz = "25000";
    num_lanes = "2";
    // lane_polarity = "4";
    tegra_sinterface = "serial_c";
    phy_mode = "DPHY";
    discontinuous_clk = "yes";
    dpcm_enable = "false";
    cil_settletime = "0";
    active_w = "1920";
    active_h = "1080";
    mode_type = "bayer";
    pixel_phase = "bggr";
    csi_pixel_bit_depth = "10";
    readout_orientation = "90";
    line_length = "2416";
    inherent_gain = "1";
    mclk_multiplier = "3.6669";
    pix_clk_hz = "81666663";
    gain_factor = "16";
    framerate_factor = "1000000";
    exposure_factor = "1000000";
    min_gain_val = "16";
    max_gain_val = "128";
    step_gain_val = "1";
    default_gain = "16";
    min_hdr_ratio = "1";
    max_hdr_ratio = "1";
    min_framerate = "30000000"; /* 30.0 fps */
    max_framerate = "30000000"; /* 30.0 fps */
    step_framerate = "1";
    default_framerate = "45000000"; /* 30.0 fps */
    min_exp_time = "60"; /* us */
    max_exp_time = "30000"; /* us */
    step_exp_time = "1";
    default_exp_time = "10000"; /* us */
    embedded_metadata_height = "0";
    };

    ........................

    ports {
    #address-cells = <1>;
    #size-cells = <0>;
    port@0 {
    reg = <0>;
    rbpcv2_ov5647_out1: endpoint {
    status = "okay";
    port-index = <1>;
    bus-width = <2>;
    remote-endpoint = <&rbpcv2_ov5647_csi_in1>;
    };
    };
    };

    };
  • 端口绑定配置

    • 通过 remote-endpoint 连接摄像头、CSI 和 VI 模块,确保视频流通路完整。

      tegra-capture-vi  {
      num-channels = <1>;
      ports {
      #address-cells = <1>;
      #size-cells = <0>;
      vi_port1: port@1 {
      reg = <0>;
      rbpcv2_ov5647_vi_in1: endpoint {
      port-index = <2>;
      bus-width = <2>;
      remote-endpoint = <&rbpcv2_ov5647_csi_out1>;
      };
      };
      };
      };

      host1x@13e00000 {
      nvcsi@15a00000 {
      num-channels = <1>;
      #address-cells = <1>;
      #size-cells = <0>;
      csi_chan1: channel@1 {
      reg = <0>;
      ports {
      #address-cells = <1>;
      #size-cells = <0>;
      csi_chan1_port0: port@0 {
      reg = <0>;
      rbpcv2_ov5647_csi_in1: endpoint@2 {
      port-index = <2>;
      bus-width = <2>;
      remote-endpoint = <&rbpcv2_ov5647_out1>;
      };
      };
      csi_chan1_port1: port@1 {
      reg = <1>;
      rbpcv2_ov5647_csi_out1: endpoint@3 {
      remote-endpoint = <&rbpcv2_ov5647_vi_in1>;
      };
      };
      };
      };
      };
      };
  • Overlay Makefile 配置,在 overlay/Makefile 添加:

    dtbo-y += tegra234-p3767-camera-p3768-ov5647.dtbo
  • 编译生成 dtbo:

    make dtbs

驱动开发与编译

  • 添加驱动源码**

    • 路径示例:drivers/media/i2c/ov5647.c
    • 推荐基于 nv_ov5693.c 修改。
    • 主要实现:
      • tegracam_device_register 注册驱动
      • 填充以下结构体:
        • tc_dev->sensor_ops(上电、下电、读写寄存器、模式设置、流控制等)
        • tc_dev->v4l2sd_internal_ops(如 open/s_stream)
        • tc_dev->tcctrl_ops(增益、曝光、帧率控制等)
    static struct tegracam_sensor_ops ov5647_sensor_ops = {
    .power_on = ov5647_power_on,
    .power_off = ov5647_power_off,
    .write_reg = ov5647_write_reg,
    .read_reg = ov5647_read_reg,
    .set_mode = ov5647_set_mode,
    .start_streaming = ov5647_start_streaming,
    .stop_streaming = ov5647_stop_streaming,
    .sensor_init = ov5647_sensor_init,
    };

    这些函数的具体实现需要根据 OV5647 的数据手册和相关文档进行编写。

    • 添加寄存器表头文件

      • 路径示例:drivers/media/i2c/ov5647_modes_tbls.h
      • 包含各分辨率、曝光等寄存器配置表,需与设备树 mode 顺序保持一致。
      static struct v4l2_subdev_internal_ops ov5647_subdev_internal_ops = {
      .open = ov5647_open,
      };
  • 驱动 Makefile 配置,在 drivers/media/i2c/Makefile 添加:

    obj-m += ov5647.o
  • 编译生成内核模块:

    make modules

系统适配与加载

拷贝文件

  • 将编译生成的 .dtbo 和 ov5647.ko 拷贝到目标设备(如 NG4520):
cd Linux_for_Tegra/source

scp ./kernel-devicetree/generic-dts/dtbs/tegra234-p3767-camera-p3768-ov5647.dtbo milesight@192.168.60.3:/home/milesight
scp ./kernel-devicetree/generic-dts/dtbs/tegra234-p3767-camera-p3768-ov5647.dtbo milesight@192.168.60.3:/home/milesight

驱动安装

  • 拷贝ov5647.ko到modules目录下,并执行depmod加载驱动
sudo cp ./ov5647.ko  /usr/lib/modules/5.15.148-tegra/updates/drivers/media/i2c/

depmod
  • 拷贝 .dtbo 到 /boot,通过 config-by-hardware.py 工具加载。

  • 完成后,重启开发板即可。

调试与验证流程

  1. 设备树加载验证

    • 检查 extlinux.conf 是否加载了 .dtbo

      cat /boot/extlinux/extlinux.conf

    • 检查设备树节点是否生效:

      cat /proc/device-tree/tegra-camera-platform/modules/module1/drivernode0/sysfs-device-tree

  2. 驱动加载验证

    • 检查驱动模块:

      lsmod | grep ov5647 sudo dmesg | grep ov5647

    • 检查 I2C 设备匹配:

      sudo i2cdetect -y -r 9

  3. 摄像头功能测试

    • 运行 nvgstcapture-1.0,检查分辨率与模式匹配、无报错。

    • 检查视频流链路:

      sudo media-ctl -p -d /dev/media0

参考

Sensor Software Driver Programming

ov5647_driver/ov5647.c at main · mkm684/ov5647_driver


如需适配其它型号摄像头,建议参考原厂数据手册及 NVIDIA 官方开发文档,步骤基本一致。